package com.iflytek.aisol.audit.iflytek.strategy.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.config.CustomException;
import com.iflytek.aisol.audit.iflytek.strategy.manage.constant.TableColumnInitConstant;
import com.iflytek.aisol.audit.iflytek.strategy.manage.dto.ChannelConfigDTO;
import com.iflytek.aisol.audit.iflytek.strategy.manage.entity.ChannelConfig;
import com.iflytek.aisol.audit.iflytek.strategy.manage.handler.ChannelHandler;
import com.iflytek.aisol.audit.iflytek.strategy.manage.handler.config.ChannelHandlerFactory;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.ChannelConfigMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.fr.FrChannelConfig2SelfMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.fr.FrChannelConfigServerInstanceMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.mapper.fr.FrGrayConfigChannelMapper;
import com.iflytek.aisol.audit.iflytek.strategy.manage.query.ChannelPageQuery;
import com.iflytek.aisol.audit.iflytek.strategy.manage.query.PageDTO;
import com.iflytek.aisol.audit.iflytek.strategy.manage.service.ChannelConfigService;
import com.iflytek.aisol.audit.iflytek.strategy.manage.utils.ConfigValidationUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * CLassName: ChannelConfigServiceImpl
 * Description:
 * Date: 2024-12-28 16:13
 * Version: 1.0
 *
 * @author hswang7
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ChannelConfigServiceImpl implements ChannelConfigService {
    private final ChannelConfigMapper channelConfigMapper;
    private final ConfigValidationUtil configValidationUtil;
    private final ChannelHandlerFactory channelHandlerFactory;
    private final FrGrayConfigChannelMapper frGrayConfigChannelMapper;
    private final FrChannelConfig2SelfMapper frChannelConfig2SelfMapper;
    private final FrChannelConfigServerInstanceMapper frChannelConfigServerInstanceMapper;
    /**
     * 新增channel配置接口
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void add(ChannelConfigDTO channelConfigDTO) {
        //新增时判断 channelId 是否有已存在的配置
        String channelId = channelConfigDTO.getChannelId();
        if(!channelConfigMapper.findWithChannelIdAndNoDeleteAndVersionMax(channelId).isEmpty()){
            throw new CustomException("您配置的channelId在数据库已经存在");
        }
        ChannelConfig channelConfig = new ChannelConfig();
        BeanUtil.copyProperties(channelConfigDTO, channelConfig);
        // 检查channel枚举类型是否能够匹配上
        // 所有前端输入的枚举类型全都要检验,不包括此处的枚举值
        String channelType = channelConfigDTO.getTemplateName().getType();
        channelConfig.setTemplateName(channelType);

        Object config = channelConfigDTO.getConfig();
        channelConfig.setConfig(JSONUtil.toJsonStr(config));

        if (!ConfigValidationUtil.isInChannelType(channelType)) {
            throw new CustomException("输入的channel类型不合法");
        }
        // 这里需要通过engine_param表实现校验 有个通用检验的工具类
        // 从数据库引擎表检查channelConfig字段类型是否合法，合法将输入的字段类型写入引擎表
        configValidationUtil.validateConfig(config,channelType);
        // 设置默认值
        channelConfig.setVersion(TableColumnInitConstant.INIT_VERSION);
        // 根据需求，初始值为1表示已删除
        channelConfig.setDeleted(TableColumnInitConstant.NOT_DELETED);
        Assert.isTrue(JSONUtil.isJson(channelConfig.getConfig()), "配置格式不正确");
        // 保存channelConfig
        channelConfigMapper.save(channelConfig);
        // 插入级联表中
        insertRelatedEntities(channelType, channelConfig);
    }

    private void insertRelatedEntities(String channelType, ChannelConfig channelConfig) {
        // 依赖的父channel和 子服务 建议从 channelConfig.getConfig() 中读取
        // 获取对应的 ChannelHandler
        ChannelHandler handler = channelHandlerFactory.getHandler(channelType);
        if (handler == null) {
            throw new CustomException("Handler not found for channel type: " + channelType);
        }
        // 调用handler的处理方法
        handler.handle(channelConfig);

        /*if(!channelType.equals("agg_default")){
            //1 如果传的是普通的channel(ive，vdt，rit，llmAudit_RAG，llmAudit)，
            // 则写入级联表frChannelConfigServerInstanceMapper
            Long id = channelConfig.getId();
            //2 转map，取出key为server_id、rag_server_id和ive_server_id的value
            Map<String, Object> jsonMap =JSONUtil.toBean(channelConfig.getConfig(), Map.class);
            if(jsonMap.containsKey("server_id")){
                Object serverId = jsonMap.get("server_id");
                // 校验配置的 serverId 在数据库中存不存在
                ServerInstance serverInstance = serviceConfigMapper.findById(Long.valueOf((String) serverId)).isPresent() ?
                        serviceConfigMapper.findById(Long.valueOf((String) serverId)).get() : null;
                Assert.notNull(serverInstance, "配置的服务id:"+ serverId +"在数据库不存在");
                // 插入级联表
                FrChannelConfigServerInstance frChannelConfigServerInstance = new FrChannelConfigServerInstance();
                frChannelConfigServerInstance.setChannelConfigId(id);
                frChannelConfigServerInstance.setServerInstanceId(Long.valueOf((String) serverId));
                frChannelConfigServerInstanceMapper.save(frChannelConfigServerInstance);
            }else if(jsonMap.containsKey("rag_server_id")){
                Object ragServerId = jsonMap.get("rag_server_id");
                // 校验配置的 serverId 在数据库中存不存在
                ServerInstance serverInstance = serviceConfigMapper.findById(Long.valueOf((String) ragServerId)).isPresent() ?
                        serviceConfigMapper.findById(Long.valueOf((String) ragServerId)).get() : null;
                Assert.notNull(serverInstance, "配置的服务id:"+ ragServerId +"在数据库不存在");
                // 插入级联表
                FrChannelConfigServerInstance frChannelConfigServerInstance = new FrChannelConfigServerInstance();
                frChannelConfigServerInstance.setChannelConfigId(id);
                frChannelConfigServerInstance.setServerInstanceId(Long.valueOf((String) ragServerId));
                frChannelConfigServerInstanceMapper.save(frChannelConfigServerInstance);
            }else if(jsonMap.containsKey("ive_server_id")){
                Object iveServerId = jsonMap.get("ive_server_id");
                // 校验配置的 serverId 在数据库中存不存在
                ServerInstance serverInstance = serviceConfigMapper.findById(Long.valueOf((String) iveServerId)).isPresent() ?
                        serviceConfigMapper.findById(Long.valueOf((String) iveServerId)).get() : null;
                Assert.notNull(serverInstance, "配置的服务id:"+ iveServerId +"在数据库不存在");
                // 插入级联表
                FrChannelConfigServerInstance frChannelConfigServerInstance = new FrChannelConfigServerInstance();
                frChannelConfigServerInstance.setChannelConfigId(id);
                frChannelConfigServerInstance.setServerInstanceId(Long.valueOf((String) iveServerId));
                frChannelConfigServerInstanceMapper.save(frChannelConfigServerInstance);
            }
        }else{
            //2 如果传的是 agg_default 类型的channel，则写入frChannelConfig2SelfMapper表中
            //2.1 首先获取 agg_suggest 里面所有的 instance_id，然后检查是不是包含 child_instances
            //2.1 如果是，则校验通过，可以插入级联表中
            Long id = channelConfig.getId();
            Map<String, Object> jsonMap =JSONUtil.toBean(channelConfig.getConfig(), Map.class);
            // 获取 child_instances 和 agg_suggest
            List<String> childInstances = (List<String>) jsonMap.get("child_instances");
            List<Map<String, Object>> aggSuggest = (List<Map<String, Object>>) jsonMap.get("agg_suggest");
            // 获取所有的 instance_id
            Set<String> instanceIds = new HashSet<>();
            for (Map<String, Object> suggestion : aggSuggest) {
                List<Map<String, String>> condition = (List<Map<String, String>>) suggestion.get("condition");
                for (Map<String, String> cond : condition) {
                    String instanceId = cond.get("instance_id");
                    instanceIds.add(instanceId);
                }
            }
            // 校验 child_instances 是不是 instance_id 的子集
            boolean isValid = childInstances.stream().allMatch(instanceIds::contains);
            if(!isValid){
                // 校验不通过
                throw new CustomException("child_instances 不是 instance_id 的子集");
            }
            //校验通过，可以插入级联表中
            for(String child:childInstances){
                FrChannelConfig2Self frChannelConfig2Self = new FrChannelConfig2Self();
                frChannelConfig2Self.setPChannelConfigId(id);
                frChannelConfig2Self.setCChannelConfigId(Long.valueOf(child));
                frChannelConfig2SelfMapper.save(frChannelConfig2Self);
            }
        }*/
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void update(Long id,ChannelConfigDTO channelConfigDTO) {
        ChannelConfig existingChannelConfig = channelConfigMapper.getOne(id);
        Assert.notNull(existingChannelConfig, "ChannelConfig 不存在");
        // 如果查出来的已经被删除则不可修改
        if(TableColumnInitConstant.DELETED.equals(existingChannelConfig.getDeleted())){
            throw new CustomException("该条记录已经被删除了，不可修改");
        }
        // 复制旧数据，并清空 ID 以插入新记录
        ChannelConfig oldChannelConfig = new ChannelConfig();
        BeanUtil.copyProperties(existingChannelConfig,oldChannelConfig);
        oldChannelConfig.setId(null);
        oldChannelConfig.setDeleted(TableColumnInitConstant.DELETED);
        channelConfigMapper.save(oldChannelConfig); // 保存旧数据
        // 更新现有数据
        existingChannelConfig.setChannelId(channelConfigDTO.getChannelId());
        existingChannelConfig.setDescription(channelConfigDTO.getDescription());
        existingChannelConfig.setConfig(JSONUtil.toJsonStr(channelConfigDTO.getConfig()));
        existingChannelConfig.setVersion(existingChannelConfig.getVersion() + 1);
        channelConfigMapper.save(existingChannelConfig);

        //把旧数据的delete恢复
        ChannelConfig channelConfig = channelConfigMapper.findById(oldChannelConfig.getId()).get();
        channelConfig.setDeleted(TableColumnInitConstant.NOT_DELETED);
        channelConfigMapper.save(channelConfig);


        // 更新级联表数据
        insertRelatedEntities(existingChannelConfig.getTemplateName(),existingChannelConfig);
    }

    /**
     * 复制级联表的历史记录到当前表
     */
    /*private void copyRelatedEntities(ChannelConfig existingChannelConfig, ChannelConfig historyChannelConfig) {
        // 复制 fr_channel_config_2_self 表数据
        List<FrChannelConfig2Self> relatedSelfRecords = frChannelConfig2SelfMapper.findByPChannelConfigId(existingChannelConfig.getId());
        for (FrChannelConfig2Self record : relatedSelfRecords) {
            FrChannelConfig2Self historyRecord = new FrChannelConfig2Self();
            BeanUtils.copyProperties(record, historyRecord);
            // ID 自增
            historyRecord.setId(null);
            // 更新为历史记录的ID
            historyRecord.setPChannelConfigId(historyChannelConfig.getId());
            frChannelConfig2SelfMapper.save(historyRecord);
        }

        // 复制 fr_channel_config_server_instance 表数据
        List<FrChannelConfigServerInstance> relatedServerInstanceRecords = frChannelConfigServerInstanceMapper.findByChannelConfigId(
                existingChannelConfig.getId());
        for (FrChannelConfigServerInstance record : relatedServerInstanceRecords) {
            FrChannelConfigServerInstance historyRecord = new FrChannelConfigServerInstance();
            BeanUtils.copyProperties(record, historyRecord);
            // ID 自增
            historyRecord.setId(null);
            // 更新为历史记录的ID
            historyRecord.setChannelConfigId(historyChannelConfig.getId());
            frChannelConfigServerInstanceMapper.save(historyRecord);
        }
    }*/
    /**
     * 更新级联表数据
     */
    /*private void updateRelatedEntities(ChannelConfig existingChannelConfig) {
        // 更新 fr_channel_config_2_self 表数据
        List<FrChannelConfig2Self> relatedSelfRecords = frChannelConfig2SelfMapper.findByPChannelConfigId(existingChannelConfig.getId());
        for (FrChannelConfig2Self record : relatedSelfRecords) {
            record.setCChannelConfigId(existingChannelConfig.getId());
            frChannelConfig2SelfMapper.save(record);
        }

        // 更新 fr_channel_config_server_instance 表数据
        List<FrChannelConfigServerInstance> relatedServerInstanceRecords = frChannelConfigServerInstanceMapper.findByChannelConfigId(
                existingChannelConfig.getId());
        for (FrChannelConfigServerInstance record : relatedServerInstanceRecords) {
            record.setChannelConfigId(existingChannelConfig.getId());
            frChannelConfigServerInstanceMapper.save(record);
        }
    }*/


    @Override
    // 如果有其他的在用的(非delete状态的)聚合策略引用时,删除时则拒绝报错
    @SuppressWarnings("all")
    public void delete(Long id) {
        // 1 先判断id在channel表中是否存在
        ChannelConfig channelConfig = channelConfigMapper.findById(id).isPresent() ? channelConfigMapper.findById(id).get() : null;
        Assert.notNull(channelConfig, "channelConfig不存在");
        // 存在，看delete状态
        if(channelConfig.getDeleted() == TableColumnInitConstant.DELETED){
            throw new CustomException("该id=" + id + "已经被删除了，不能再次删除");
        }
        // 2 删除时判断是否有级联使用
        if (!frGrayConfigChannelMapper.findByChannelConfigId(id).isEmpty()) {
            throw new CustomException("该channel_config_id在级联表frGrayConfigChannel已经配置过了，不能删除");
        }
        if (!frChannelConfigServerInstanceMapper.findByChannelConfigId(id).isEmpty()) {
            throw new CustomException("该channel_config_id在级联表frChannelConfigServerInstance已经配置过了，不能删除");
        }
        if (!frChannelConfig2SelfMapper.findByPChannelConfigId(id).isEmpty()) {
            throw new CustomException("该p_channel_config_id在级联表frChannelConfig2Self已经配置过了，不能删除");
        }
        if (!frChannelConfig2SelfMapper.findByCChannelConfigId(id).isEmpty()) {
            throw new CustomException("该c_channel_config_id在级联表frChannelConfig2Self已经配置过了，不能删除");
        }
        channelConfig.setDeleted(Math.toIntExact(TableColumnInitConstant.DELETED));
        channelConfigMapper.save(channelConfig);
    }

    @Override
    public PageDTO<ChannelConfig> queryPage(ChannelPageQuery query) {
        Integer pageNo = query.getPageNo();
        Integer pageSize = query.getPageSize();
        // 开启分页
        try {
            //PageHelper.startPage(pageNo, pageSize);
            // 构建分页条件和排序字段
            Pageable pageable;
            if (StrUtil.isNotBlank(query.getSortBy())) {
                pageable = PageRequest.of(pageNo - 1, pageSize,
                        query.getIsAsc() ? Sort.by(query.getSortBy()).ascending() : Sort.by(query.getSortBy()).descending());
            } else {
                // 默认排序，使用更新时间降序
                pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(ChannelConfig.Fields.updateTime).descending());
            }

            // 查询数据库
            Page<ChannelConfig> page = channelConfigMapper.findPage(
                    query.getChannelId(), query.getVersion(), query.getDeleted(), query.getTemplateName(),pageable);

            // 返回结果
            return new PageDTO<>(page.getTotalElements(), (long) page.getTotalPages(), page.getContent());
        } finally {
            PageHelper.clearPage();
        }

    }

}
